package hotel.meituan.oversea.biz.controller;


import com.alibaba.fastjson.JSONObject;
import hotel.base.oversea.constant.CommonConstants;
import hotel.base.oversea.utils.DateUtil;
import hotel.base.oversea.utils.Result;
import hotel.meituan.oversea.api.vo.overseaRequestVO.MtHotelChangeCallbackVO;
import hotel.meituan.oversea.api.vo.overseaRequestVO.MtHotelDetailVO;
import hotel.meituan.oversea.api.vo.overseaRequestVO.MtHotelGoodsPriceVO;
import hotel.meituan.oversea.api.vo.overseaRequestVO.MtHotelGoodsRpVO;
import hotel.meituan.oversea.api.vo.overseaRequestVO.MtHotelOrderBookingVO;
import hotel.meituan.oversea.api.vo.overseaRequestVO.MtHotelOrderCancelVO;
import hotel.meituan.oversea.api.vo.overseaRequestVO.MtHotelOrderCheckVO;
import hotel.meituan.oversea.api.vo.overseaRequestVO.OrderQueryParamVO;
import hotel.meituan.oversea.biz.service.oversea.MtHotelOverseaService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;

/**
 * @Description 美团国际线接口
 * @Author Chen_l
 * @Date 2021/8/2 18:07
 */
@Slf4j
@RestController
@RequestMapping("/mtOverSeaHotel")
@Api(value = "MtHotelController", tags = {"美团境外酒店接口"})
public class MtHotelOverseaController {
    @Autowired
    private MtHotelOverseaService mtHotelOverseaService;

    /**
     * 接口说明：获取可分销的境外酒店ID列表
     * HTTP方式：POST
     * 提交形式：JSON
     * 接口限流：1000次/分钟
     */
    @PostMapping("/getMtHotelIds")
    @ApiOperation(value = "查询境外酒店ID列表接口", notes = "必须经过auth授权")
    public Result<Object> getMtHotelIds(@RequestBody JSONObject jsonObject) {
        int maxId = jsonObject.get("maxId") == null ? -1 : (int) jsonObject.get("maxId");
        int pageSize = jsonObject.get("pageSize") == null ? -1 : (int) jsonObject.get("pageSize");
        if (-1 == maxId) {
            return new Result<>("maxId不可以为空", CommonConstants.REQUEST_ERROR);
        }
        if (-1 == pageSize) {
            return new Result<>("pageSize不可以为空", CommonConstants.REQUEST_ERROR);
        }
        return mtHotelOverseaService.mtHotelGetIds(maxId, pageSize);
    }

    /**
     * 接口说明：查询境外酒店静态信息
     * HTTP方式：POST
     * 提交形式：JSON
     * 接口限流：1000次/分钟
     */
    @PostMapping("/getMtHotelDetail")
    @ApiOperation(value = "查询境外酒店详情接口", notes = "必须经过auth授权")
    public Result<Object> getMtHotelDetail(@RequestBody MtHotelDetailVO mtHotelDetailVo) {
        List<Long> hotelIds = mtHotelDetailVo.getHotelIds();

        if (hotelIds == null && hotelIds.size() > 0) {
            return new Result<>("HotelIds不能为空", CommonConstants.REQUEST_ERROR);
        } else {
            if (hotelIds.size() > 20) {
                return new Result<>("查询数量溢出，一次最多只能查询20个", CommonConstants.REQUEST_ERROR);
            }
        }
        return mtHotelOverseaService.mtHotelGetDetails(mtHotelDetailVo);
    }

    /**
     * 接口说明：查询境外酒店物理房型信息
     * HTTP方式：POST
     * 提交形式：JSON
     * 接口限流：1000次/分钟
     */
    @PostMapping("/getMtHotelRealRoom")
    @ApiOperation(value = "查询境外酒店物理房型信息", notes = "必须经过auth授权")
    public Result<Object> getMtHotelRealRoom(@RequestBody JSONObject jsonObject) {
        List<Long> hotelIds = (List<Long>) jsonObject.get("hotelIds");
        if (CollectionUtils.isEmpty(hotelIds)) {
            return new Result<>("hotelIds不能为空", CommonConstants.REQUEST_ERROR);
        }
        if (hotelIds.size() > 20) {
            return new Result<>("超出，查询酒店最多20", CommonConstants.REQUEST_ERROR);
        }
        return mtHotelOverseaService.mtHotelGetRealRoom(hotelIds);
    }

    /**
     * 根据酒店ID列表, 批量查询所有产品的详细信息, 包括产品对应房型
     * 基本信息、取消规则、预订规则、服务条款、使用规则、价格信息等
     * 适用于落地模式，批量同步酒店的产品并进行保存
     */
    @PostMapping("/getMtHotelGoodsRp")
    @ApiOperation(value = "批量查询境外酒店产品列表", notes = "必须经过auth授权")
    public Result<Object> getMtHotelGoodsRp(@RequestBody @Valid MtHotelGoodsRpVO mtHotelGoodsRpVO) {
        String checkinDate = mtHotelGoodsRpVO.getCheckinDate();//入住日期
        String checkoutDate = mtHotelGoodsRpVO.getCheckoutDate();//离店日期
        if (checkinDate == null) {
            String nowDate = DateUtil.formatDate(new Date(), "yyyy-MM-dd");
            mtHotelGoodsRpVO.setCheckinDate(nowDate);
        } else {
            LocalDate start = LocalDate.parse(checkinDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            LocalDate end = LocalDate.parse(checkoutDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            Period between = Period.between(start, end);
            int days = between.getDays();
            if (days > 28) {
                return new Result<>("离店日期与入住日期相差不能超过28天");
            }
        }
        //空值时默认返回面向C端用户的产品
        Integer salesChannel = mtHotelGoodsRpVO.getSalesChannel();
        if (salesChannel == null || salesChannel.equals("")) {
            mtHotelGoodsRpVO.setSalesChannel(1);
        }
        return mtHotelOverseaService.mtHotelGetGoodsRp(mtHotelGoodsRpVO);

    }

    /**
     * 该接口为美团的价格缓存接口，请求QPS限制150以内，每次最多请求10个酒店，最多请求15天
     * 分销商可用该接口请求多天，获取每个产品每天的价格数据，应用于分销商内部缓存。
     * 例如: startDate=“2019-09-01”，endDate="2019-09-10"，商家设置的产品价格日历为["2019-08-07", "2019-09-07"]，
     * 则返回的产品价格日历区间为["2019-09-01", "2016-09-07"]
     */
    @PostMapping("/getMtHotelGoodsPrice")
    @ApiOperation(value = "查询产品价格日历", notes = "必须经过auth授权")
    public Result<Object> getMtHotelGoodsPrice(@RequestBody @Valid MtHotelGoodsPriceVO mtHotelGoodsPriceVO) {

        return mtHotelOverseaService.mtHotelGetGoodsPrice(mtHotelGoodsPriceVO);
    }

    /**
     * 此接口适用于在真正下单前先进行一次下单前校验，校验房态、库存等信息是否满足下单请求，从而可以降低真正下单时的失败率，提升用户体验。
     * 此接口校验通过时会返回此产品最新的价格信息，调用方可用返回的价格信息来调用hotel.oversea.order.booking接口进行真正下单。
     * 下单前校验校验通过不代表下单时一定能成功，在此时间差内房态信息等可能会发生变更。
     * 下单前校验接口是在真正要下单之前才应该使用，不应该将下单前校验接口作为查询房态及价格的工具，分销侧会有限流，次数过多会影响调用方正常业务使用。
     * 接口限流：1000次/分钟
     */
    @PostMapping("/getMtHotelOrderCheck")
    @ApiOperation(value = "下单前校验", notes = "必须经过auth授权")
    public Result<Object> getMtHotelOrderCheck(@RequestBody @Valid MtHotelOrderCheckVO mtHotelGoodsPriceVO) {

        return mtHotelOverseaService.mtHotelOrderCheck(mtHotelGoodsPriceVO);
    }


    /**
     * 注意:
     * 调用预约下单接口前，分销商需要对用户提交的下单数据进行校验。校验通过后分销商再调用分销平台的预约下单接口
     * 当出现请求超时、网络异常、返回异常字符等情况时，分销商可重新调用预约下单接口； 当分销平台返回明确的响应数据时，分销商根据响应数据中的code值决定是否需要重新调用预约下单接口。 对预约下单请求进行重试时，请求参数中的distributorOrderId值必须保持一致
     * 预约下单请求成功后，分销商需要保存分销平台订单号
     * 下单成功不代表境外酒店房间已预订成功，预订需要境外酒店商家进行确认。 分销平台将通过4.1 订单状态变更通知接口将商家确认结果通知分销商， 分销商也可以通过3.4 查询订单接口主动查询订单最新状态进行同步
     * 分销平台在接收到预约下单请求后会对总价和结算价进行校验
     * 接口限流：1000次/分钟
     */
    @PostMapping("/getMtHotelOrderBooking")
    @ApiOperation(value = "预约下单", notes = "必须经过auth授权")
    public Result<Object> getMtHotelOrderBooking(@RequestBody @Valid MtHotelOrderBookingVO mtHotelGoodsPriceVO) {

        return mtHotelOverseaService.mtHotelOrderBooking(mtHotelGoodsPriceVO);
    }

    /**
     * 注意:
     * 用户申请退款时，分销商调用取消订单接口。不满足取消规则时, 则取消失败。响应结果返回取消中时，需等待订单状态变更推送通知。
     * 用户入住后，无法取消。由于特殊原因，如商家原因导致用户需要退款时，需要客服介入，由美团客服操作退款。
     * 预订中订单暂时无法操作取消，如需取消，需要找客服操作。
     * 接口限流：1000次/分钟
     */
    @PostMapping("/MtHotelOrderCancel")
    @ApiOperation(value = "取消订单", notes = "必须经过auth授权")
    public Result<Object> MtHotelOrderCancel(@RequestBody @Valid MtHotelOrderCancelVO mtHotelGoodsPriceVO) {

        return mtHotelOverseaService.mtHotelOrderCancel(mtHotelGoodsPriceVO);
    }


    /**
     * 注意:
     * 间夜信息说明，roomNights数量=入住天数*房间数量， 例如用户预订2间房，入住日期是2017-06-11，离店日期是2017-06-13，则间夜roomNights数量为4，其中2个间夜bizDate=2017-06-11，2个间夜bizDate=2017-06-12。
     * 订单基本信息中订单状态对应整个订单的状态，如果用户入住，则订单状态是：已入住(50）。目前不支持分销商调用接口退部分间夜，需要美团客服和境外酒店供应商确认才能操作，当订单状态是：已消费退款(40）时，说明存在部分间夜或全部间夜通过美团客服操作退款，已退款间夜payStatus=2050.
     * 接口限流：1000次/分钟
     * /
     */
    @PostMapping("/MtHotelOrderQuery")
    @ApiOperation(value = "查询订单", notes = "必须经过auth授权")
    public Result<Object> MtHotelOrderQuery(@RequestBody @Valid OrderQueryParamVO orderQueryParamVO) {
        return mtHotelOverseaService.mtHotelOrderQuery(orderQueryParamVO);
    }


    /**
     * 接口说明：
     * 当订单状态发生变化时，分销平台将通过该接口把最新的订单状态通知给分销商
     * 需要分销商将接收状态变更的URL地址提供给分销平台, 建议订单变更接口与其他接口分开,
     * 原因是其他接口回调频次很高, 如果分销商系统处理能力跟不上, 容易导致订单状态变更同步不及时
     * HTTP方式：POST
     * 提交形式：JSON
     * 接口限流：1000次/分钟
     * /
     */
    @PostMapping("/MtHotelOrderCallback")
    @ApiOperation(value = "订单状态变更通知", notes = "必须经过auth授权")
    public Result<Object> MtHotelChangeCallback(@RequestBody @Valid MtHotelChangeCallbackVO mtHotelChangeCallbackVO) {
        return mtHotelOverseaService.mtHotelChangeCallback(mtHotelChangeCallbackVO);
    }
}
